/**
 * JSON处理工具模块
 * 提供增强的JSON操作功能，包括安全解析、格式化、路径访问等
 */

/**
 * 安全的JSON解析，不会抛出异常
 * @param {string} str JSON字符串
 * @param {*} defaultValue 解析失败时的默认值
 * @returns {*} 解析结果或默认值
 */
export function parseJson(str, defaultValue = null) {
  try {
    return JSON.parse(str);
  } catch (e) {
    return defaultValue;
  }
}

/**
 * 安全的JSON字符串化
 * @param {*} obj 要序列化的对象
 * @param {*} defaultValue 序列化失败时的默认值
 * @param {number} space 缩进空格数
 * @returns {string} JSON字符串或默认值
 */
export function toJsonString(obj, defaultValue = '{}', space = 0) {
  try {
    return JSON.stringify(obj, null, space);
  } catch (e) {
    return defaultValue;
  }
}

/**
 * 格式化JSON字符串（美化输出）
 * @param {string|Object} json JSON字符串或对象
 * @param {number} space 缩进空格数，默认2
 * @returns {string} 格式化后的JSON字符串
 */
export function formatJson(json, space = 2) {
  try {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;
    return JSON.stringify(obj, null, space);
  } catch (e) {
    throw new Error('JSON格式化失败：' + e.message);
  }
}

/**
 * 压缩JSON字符串（移除空白字符）
 * @param {string|Object} json JSON字符串或对象
 * @returns {string} 压缩后的JSON字符串
 */
export function compressJson(json) {
  try {
    const obj = typeof json === 'string' ? JSON.parse(json) : json;
    return JSON.stringify(obj);
  } catch (e) {
    throw new Error('JSON压缩失败：' + e.message);
  }
}

/**
 * 通过路径获取JSON对象中的值
 * @param {Object} obj JSON对象
 * @param {string} path 路径，使用点号分隔，如 'user.profile.name'
 * @param {*} defaultValue 默认值
 * @returns {*} 获取到的值或默认值
 */
export function getByPath(obj, path, defaultValue = undefined) {
  if (!obj || typeof obj !== 'object' || typeof path !== 'string') {
    return defaultValue;
  }

  const keys = path.split('.');
  let current = obj;

  for (const key of keys) {
    if (current === null || current === undefined || typeof current !== 'object') {
      return defaultValue;
    }

    // 处理数组索引
    if (Array.isArray(current) && /^\d+$/.test(key)) {
      current = current[parseInt(key, 10)];
    } else {
      current = current[key];
    }
  }

  return current !== undefined ? current : defaultValue;
}

/**
 * 通过路径设置JSON对象中的值
 * @param {Object} obj JSON对象
 * @param {string} path 路径，使用点号分隔，如 'user.profile.name'
 * @param {*} value 要设置的值
 * @returns {Object} 修改后的对象
 */
export function setByPath(obj, path, value) {
  if (!obj || typeof obj !== 'object' || typeof path !== 'string') {
    throw new Error('对象和路径参数无效');
  }

  const keys = path.split('.');
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];

    if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
      // 检查下一个键是否为数字（数组索引）
      const nextKey = keys[i + 1];
      current[key] = /^\d+$/.test(nextKey) ? [] : {};
    }

    current = current[key];
  }

  const lastKey = keys[keys.length - 1];
  current[lastKey] = value;

  return obj;
}

/**
 * 删除JSON对象中指定路径的属性
 * @param {Object} obj JSON对象
 * @param {string} path 路径，使用点号分隔
 * @returns {boolean} 是否成功删除
 */
export function deleteByPath(obj, path) {
  if (!obj || typeof obj !== 'object' || typeof path !== 'string') {
    return false;
  }

  const keys = path.split('.');
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
      return false;
    }
    current = current[key];
  }

  const lastKey = keys[keys.length - 1];
  if (Array.isArray(current) && /^\d+$/.test(lastKey)) {
    current.splice(parseInt(lastKey, 10), 1);
  } else {
    delete current[lastKey];
  }

  return true;
}

/**
 * 检查路径是否存在于JSON对象中
 * @param {Object} obj JSON对象
 * @param {string} path 路径，使用点号分隔
 * @returns {boolean} 路径是否存在
 */
export function hasPath(obj, path) {
  if (!obj || typeof obj !== 'object' || typeof path !== 'string') {
    return false;
  }

  const keys = path.split('.');
  let current = obj;

  for (const key of keys) {
    if (current === null || current === undefined || typeof current !== 'object') {
      return false;
    }

    if (Array.isArray(current) && /^\d+$/.test(key)) {
      const index = parseInt(key, 10);
      if (index >= current.length) {
        return false;
      }
      current = current[index];
    } else {
      if (!(key in current)) {
        return false;
      }
      current = current[key];
    }
  }

  return true;
}

/**
 * 深度合并两个JSON对象
 * @param {Object} target 目标对象
 * @param {Object} source 源对象
 * @returns {Object} 合并后的对象
 */
export function mergeJson(target, source) {
  if (!target || typeof target !== 'object') {
    target = {};
  }

  if (!source || typeof source !== 'object') {
    return target;
  }

  const result = { ...target };

  for (const key in source) {
    if (source.hasOwnProperty(key)) {
      if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
        result[key] = mergeJson(result[key], source[key]);
      } else {
        result[key] = source[key];
      }
    }
  }

  return result;
}

/**
 * 扁平化JSON对象
 * @param {Object} obj 要扁平化的对象
 * @param {string} prefix 键前缀
 * @param {string} separator 分隔符，默认为点号
 * @returns {Object} 扁平化后的对象
 */
export function flattenJson(obj, prefix = '', separator = '.') {
  const result = {};

  function flatten(current, currentPrefix) {
    if (typeof current === 'object' && current !== null && !Array.isArray(current)) {
      for (const key in current) {
        if (current.hasOwnProperty(key)) {
          const newKey = currentPrefix ? `${currentPrefix}${separator}${key}` : key;
          flatten(current[key], newKey);
        }
      }
    } else {
      result[currentPrefix] = current;
    }
  }

  flatten(obj, prefix);
  return result;
}

/**
 * 反扁平化JSON对象
 * @param {Object} obj 扁平化的对象
 * @param {string} separator 分隔符，默认为点号
 * @returns {Object} 反扁平化后的对象
 */
export function unflattenJson(obj, separator = '.') {
  const result = {};

  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      setByPath(result, key.replace(new RegExp(`\\${separator}`, 'g'), '.'), obj[key]);
    }
  }

  return result;
}

/**
 * 比较两个JSON对象是否相等（深度比较）
 * @param {*} obj1 第一个对象
 * @param {*} obj2 第二个对象
 * @returns {boolean} 是否相等
 */
export function isEqual(obj1, obj2) {
  if (obj1 === obj2) {
    return true;
  }

  if (obj1 === null || obj2 === null || obj1 === undefined || obj2 === undefined) {
    return obj1 === obj2;
  }

  if (typeof obj1 !== typeof obj2) {
    return false;
  }

  if (typeof obj1 !== 'object') {
    return obj1 === obj2;
  }

  if (Array.isArray(obj1) !== Array.isArray(obj2)) {
    return false;
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (const key of keys1) {
    if (!keys2.includes(key)) {
      return false;
    }
    if (!isEqual(obj1[key], obj2[key])) {
      return false;
    }
  }

  return true;
}

/**
 * 深拷贝JSON对象
 * @param {*} obj 要拷贝的对象
 * @returns {*} 拷贝后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }

  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }

  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }

  const cloned = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key]);
    }
  }

  return cloned;
}

/**
 * 验证JSON字符串格式
 * @param {string} str 要验证的字符串
 * @returns {boolean} 是否为有效的JSON格式
 */
export function isValidJson(str) {
  if (typeof str !== 'string') {
    return false;
  }

  try {
    JSON.parse(str);
    return true;
  } catch (e) {
    return false;
  }
}

/**
 * 获取JSON对象的所有路径
 * @param {Object} obj JSON对象
 * @param {string} prefix 路径前缀
 * @param {string} separator 分隔符
 * @returns {Array<string>} 所有路径的数组
 */
export function getAllPaths(obj, prefix = '', separator = '.') {
  const paths = [];

  function traverse(current, currentPrefix) {
    if (typeof current === 'object' && current !== null && !Array.isArray(current)) {
      for (const key in current) {
        if (current.hasOwnProperty(key)) {
          const newPath = currentPrefix ? `${currentPrefix}${separator}${key}` : key;
          paths.push(newPath);
          traverse(current[key], newPath);
        }
      }
    }
  }

  traverse(obj, prefix);
  return paths;
}

/**
 * 过滤JSON对象，只保留指定的键
 * @param {Object} obj 源对象
 * @param {Array<string>} keys 要保留的键数组
 * @returns {Object} 过滤后的对象
 */
export function pick(obj, keys) {
  if (!obj || typeof obj !== 'object' || !Array.isArray(keys)) {
    return {};
  }

  const result = {};
  for (const key of keys) {
    if (obj.hasOwnProperty(key)) {
      result[key] = obj[key];
    }
  }

  return result;
}

/**
 * 过滤JSON对象，排除指定的键
 * @param {Object} obj 源对象
 * @param {Array<string>} keys 要排除的键数组
 * @returns {Object} 过滤后的对象
 */
export function omit(obj, keys) {
  if (!obj || typeof obj !== 'object' || !Array.isArray(keys)) {
    return obj;
  }

  const result = { ...obj };
  for (const key of keys) {
    delete result[key];
  }

  return result;
}